import hashlib
import sqlite3
import time
import tkinter as tk
import tkinter.messagebox
from pathlib import Path
from tkinter.constants import END


class DataBase:
    def __init__(self):
        self.path = Path(Path(__file__).parent, "users.db")
        self.db = sqlite3.connect(self.path)

    def creat_if(self):  # 判断表和数据库是否存在
        try:
            self.db.execute("SELECT USERNAME FROM USER_GUI WHERE ID=1;")
            print("数据库存在，请继续")
        except:
            print("数据库不存在，已新建")
            sql = """
            CREATE TABLE USER_GUI(
                ID INTEGER NOT NULL PRIMARY KEY,
                USERNAME TEXT NOT NULL UNIQUE,
                PASSWORD TEXT NOT NULL,
                SIGN_UP_TIME TIMESTAMP DEFAULT NULL,
                LOCK TEXT NOT NULL DEFAULT 'FALSE',
                LOCKTIME TIMESTAMP DEFAULT NULL,
                PASSWORD_FALSE_COUNT INTEGER DEFAULT 0
            );"""
            self.db.execute(sql)
            self.db.commit()

    def insert(self, username, password):  # 插入新记录
        password_md5 = hashlib.md5("add_salt".encode(encoding="utf-8"))  # 加盐增加安全性
        password_md5.update(password.encode(encoding="utf-8"))
        sql = """
            INSERT INTO
                USER_GUI (USERNAME, PASSWORD, SIGN_UP_TIME)
            VALUES
                ('{}', '{}', '{}')
        """.format(
            username,
            password_md5.hexdigest(),
            time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
        )
        self.db.execute(sql)
        self.db.commit()

    def select(self, username):  # 查询
        sql = """
            SELECT
                *
            FROM
                USER_GUI
            WHERE
                USERNAME = '{}'
        """.format(
            username
        )
        user_info = self.db.execute(sql)
        return user_info.fetchone()

    def update_lock(self, username):  # 锁定该用户
        sql = """
            UPDATE
                USER_GUI
            SET
                LOCK = 'TRUE',
                LOCKTIME = '{}'
            WHERE
                USERNAME = '{}'
        """.format(
            time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), username
        )
        self.db.execute(sql)
        self.db.commit()

    def update_unlock(self, username):  # 解锁
        sql = """
            UPDATE
                USER_GUI
            SET
                LOCK = 'FALSE',
                LOCKTIME = NULL,
                PASSWORD_FALSE_COUNT = 0
            WHERE
                USERNAME = '{}'
        """.format(
            username
        )
        self.db.execute(sql)
        self.db.commit()

    def update_password_false_count(self, username, password_false_count):  # 更新累计输错次数
        sql = """
            UPDATE
                USER_GUI
            SET
                PASSWORD_FALSE_COUNT = {}
            WHERE
                USERNAME = '{}'        
        """.format(
            password_false_count, username
        )
        self.db.execute(sql)
        self.db.commit()

    def close_db(self):  # 关闭连接
        self.db.close()


class Page_sign_up:  # 注册页面
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("sign_up")
        self.window.geometry("500x300")
        self.window.config(bg="#0F375A")
        self.lf1()
        self.lf2()
        self.db = DataBase()
        self.window.mainloop()

    def lf1(self):
        lf = tk.LabelFrame(self.window)
        lf.place(x=20, y=20)

        lb1 = tk.Label(lf, text="用户名:")
        lb1.grid(row=1, column=1)

        entry_username = tk.Entry(lf, width=30)
        entry_username.grid(row=1, column=2)

        b1 = tk.Button(lf, text="检查用户名是否被占用", command=self.check_username)
        b1.grid(row=1, column=3)

        lb2 = tk.Label(lf, text="密码:")
        lb2.grid(row=2, column=1)

        entry_password = tk.Entry(lf, width=30)
        entry_password.grid(row=2, column=2)

        self.entry_username = entry_username
        self.entry_password = entry_password

    def lf2(self):
        lf = tk.LabelFrame(self.window)
        lf.place(x=20, y=100)

        b1 = tk.Button(lf, text="提交", command=self.submit)
        b1.grid(row=1, column=1)

        b2 = tk.Button(lf, text="重置", command=self.reset)
        b2.grid(row=1, column=2)

        b3 = tk.Button(lf, text="返回", command=self.turn_back_sign_in)
        b3.grid(row=1, column=3)

    def check_username(self):  # 检查按钮
        self.db.creat_if()
        if self.db.select(self.entry_username.get()) == None:  # 判断用户是否存在
            tkinter.messagebox.showinfo(title="Tips", message="检查按钮：此用户名未被注册")
        else:
            tkinter.messagebox.showinfo(title="Tips", message="检查按钮：用户名重复！")

    def reset(self):  # 重置按钮
        self.entry_username.delete(0, END)
        self.entry_password.delete(0, END)

    def turn_back_sign_in(self):  # 返回按钮
        self.window.destroy()
        Page_sign_in()

    def submit(self):  # 提交按钮
        self.db.creat_if()
        username = self.entry_username.get()
        password = self.entry_password.get()

        if self.db.select(username) == None:  # 判断用户是否存在
            self.db.insert(username, password)
            print("注册成功！")
            tkinter.messagebox.showinfo(title="Tips", message="注册成功！")
        else:
            tkinter.messagebox.showinfo(title="Tips", message="提交结点，提示用户名重复！")
            print("提交结点，提示用户名重复！")


class Page_sign_in:  # 登录页面
    def __init__(self):

        self.window = tk.Tk()
        self.window.title("main")
        self.window.geometry("500x300")
        self.window.config(bg="#F9C03D")
        self.labelframe_1()
        self.labelframe_2()
        self.db = DataBase()
        self.db.creat_if()
        self.window.mainloop()

    def labelframe_1(self):
        lf = tk.LabelFrame(
            self.window, text="Login", font=("微软雅黑", 10, "bold"), padx=10, pady=10
        )
        lf.place(x=20, y=20)

        label_username = tk.Label(lf, text="用户:", font=("微软雅黑", 10, "bold"), height=2)
        label_username.grid(row=1, column=1)

        entry_username = tk.Entry(lf, width=30, font=("微软雅黑", 10))
        entry_username.grid(row=1, column=2)

        label_password = tk.Label(lf, text="密码:", font=("微软雅黑", 10, "bold"), height=2)
        label_password.grid(row=2, column=1)

        entry_password = tk.Entry(lf, width=30, font=("微软雅黑", 10), show="*")
        entry_password.grid(row=2, column=2)

        button = tk.Button(lf, text="登录", width=40, height=1, command=self.main)
        button.grid(row=3, column=1, columnspan=2)

        self.entry_username = entry_username
        self.entry_password = entry_password

    def labelframe_2(self):
        lf = tk.LabelFrame(
            self.window, text="", font=("微软雅黑", 10, "bold"), padx=10, pady=10
        )
        lf.place(x=20, y=200)

        b2 = tk.Button(lf, text="注册", width=10, height=1, command=self.sign_up)
        b2.grid(row=1, column=1)

        b3 = tk.Button(lf, text="重置密码", width=10, height=1)
        b3.grid(row=1, column=3)

    def password_is_right(self):
        username = self.entry_username.get()
        password = self.entry_password.get()
        user_info = self.db.select(username)

        password_md5 = hashlib.md5("add_salt".encode(encoding="utf-8"))  # 加盐增加安全性
        password_md5.update(password.encode(encoding="utf-8"))
        if password_md5.hexdigest() == user_info[2]:
            print("密码正确，登录成功")
            tkinter.messagebox.showinfo(title="Tips", message="密码正确，登录成功")
            self.window.destroy()
            Page_end()
        else:
            password_false_count = user_info[6]
            if password_false_count == 0:
                self.db.update_password_false_count(username, 1)
                print("从来没错过,还可再试2次")
                tkinter.messagebox.showinfo(title="Tips", message="从来没错过,还可再试2次")
            elif password_false_count == 1:
                self.db.update_password_false_count(username, 2)
                print("还可再试1次")
                tkinter.messagebox.showinfo(title="Tips", message="还可再试1次")
            elif password_false_count == 2:
                self.db.update_password_false_count(username, 3)
                self.db.update_lock(username)
                print("错3次，已锁定")
                tkinter.messagebox.showinfo(title="Tips", message="错3次，已锁定")
            else:
                print("不应该有这种情况")
                tkinter.messagebox.showinfo(title="Tips", message="不应该有这种情况，代码逻辑有误")

    def main(self):
        username = self.entry_username.get()
        user_info = self.db.select(username)

        if self.db.select(username) == None:  # 用户是否存在
            print("用户未注册，请先注册")
            tkinter.messagebox.showinfo(title="Tips", message="用户未注册，请先注册")
        else:
            if user_info[4] == "FALSE":  # 用户是否锁定
                self.password_is_right()
            else:
                locktime_db = time.mktime(
                    time.strptime(user_info[5], "%Y-%m-%d %H:%M:%S")
                )
                if time.time() - locktime_db > 60:
                    print("虽已锁定，但已超出60s，可重试")
                    self.db.update_unlock(username)
                    self.password_is_right()
                else:
                    print("已锁定，60s后再试")
                    tkinter.messagebox.showinfo(title="Tips", message="已锁定，N MIN后再试")

    def sign_up(self):
        self.window.destroy()
        Page_sign_up()


class Page_end:
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("end")
        self.window.geometry("300x400")
        self.window.config(bg="#D05667")
        self.label = tk.Label(
            self.window,
            text="登录成功",
            font=("微软雅黑", 16),
        )
        self.label.pack(side="top", expand="yes")
        self.window.mainloop()


if __name__ == "__main__":
    Page_sign_in()
